-
Notifications
You must be signed in to change notification settings - Fork 277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Minimal miri support #803
Minimal miri support #803
Conversation
Should address rust-lang/miri#932
r? @gnzlbg (rust_highfive has picked a reviewer for you, use r? to override) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
@@ -64,7 +64,10 @@ mod bit; | |||
mod cache; | |||
|
|||
cfg_if! { | |||
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { | |||
if #[cfg(miri)] { | |||
#[path = "os/other.rs"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please add a comment here saying that on miri all features are always disabled features that are not enabled at compile-time (e.g. cfg(target_feature) == true
) are always disabled ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment should maybe add that this is correct because for features for which cfg(target_feature)
is true, the run-time detection logic is not invoked, so is_x86_feature_detected!
will return the same answer as miri for those anyways.
cc @RalfJung
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no idea what this means. I have never used run-time feature detection so none of this code here means anything to me.
Co-Authored-By: gnzlbg <[email protected]>
Can we add a test to test that this works ? E.g. a build job that tries to |
On our side or on the miri side? |
On our side. |
I was kind of thinking maybe |
|
If someone volunteers to update the test runner with that would be great :) |
I opened an issue for the CI task since I'd like to merge this now, is it fine to ignore the cirrus-ci? |
@lu-zero see this: rust-lang/rust#64683 (comment) We probably should remove |
Can't we make it so that the optimization "features known at compile-time statically return |
This code never has UB in Rust today: fn main() {
if !is_x86_feature_detected!("sse") {
if cfg!(target_feature = "sse") {
// invoke UB
// note: this never happens, since SSE cannot be
// enabled and disabled at the same time
}
}
} If |
The optimization is implemented here: https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/src/detect/macros.rs#L97 |
Fair. OTOH, UB in Miri is not the total catastrophe it usually is. So that seems better to me than the alternative. |
In practice, there is also a lot of Rust code like this: if is_x86_feature_detected!("avx") {
do_avx_thingy()
} else {
do_sse_fallback() // will try to run an intrinsic that miri doesn't support
} so if we were to always return if is_x86_feature_detected!("avx") {
do_avx_thingy()
} else if is_x86_feature_detected!("sse") {
do_sse_fallback()
} else {
do_miri_fallback()
} and that would work. With the current implementation, this example will initially error with a deep error in the miri stack when it encounters the first sse intrinsic within if cfg!(miri) {
do_miri_fallback()
} else if is_x86_feature_detected!("avx") {
do_avx_thingy()
} else {
do_sse_fallback()
} instead. |
if is_x86_feature_detected!("avx") {
do_avx_thingy()
} else {
do_sse_fallback() // will try to run an intrinsic that miri doesn't support
} Sure, code that always requires SIMD cannot work in Miri without being adjusted. if cfg!(miri) {
do_miri_fallback()
} else if is_x86_feature_detected!("avx") {
do_avx_thingy()
} else {
do_sse_fallback()
} This would be an alternative, yes. But using feature flags seems more generally applicable and also more portable across platforms? Like, the first code above does not work on ARM. |
The thing is feature flags are currently exclusively additive, while "miri" would be like a feature flag that disables some things, and that often ends up causing trouble. For example, by disabling all features, if is_x86_feature_detected!("sse") {
// 64-bit fp arithmetic
} else {
// 80-bit fp arithmetic is enabled when SSE is disabled
} so when running on miri, code that queries which kind of arithmetic is available might end up being subtly confused by the answer of I don't mind much either way, but we currently promise that
|
Thinking more about the whole problem, code like this: if cfg!(target_feature = "sse") {
sse_fn()
} else {
miri_fallback()
} won't work under miri either because independently of what I think I would prefer for |
That would be useful for alternative codegen backends. (not much anymore for cg_clif though, as most sse usage I have seen is already emulated by it at the moment) |
Miri already sets some flags for all code it runs; we could add a |
|
Yes, maybe. I'm not sure, but I think this could work. The main "issue" is that target features are part of what constitutes a target, but since when running on miri we don't do any kind of codegen, then I think the flag can just tell
Not for
Maybe? When people use The main issue is that target-features are a property of the target, e.g., I think it is unrealistic to expect that all backends (or miri) support all intrinsics or language features at least from the get go. I think the best thing to do would be to just disable them for those backends. E.g. we could add For miri, as long as the program doesn't trying to execute them at run-time, there is no issue, so some kind of "run-time" detection is necessary. The problem is that the run-time detection system is coarse, in the sense that detecting |
Most SIMD code does runtime feature detection, so compiling code with those intrinsics should work, as you have to patch the whole world otherwise. Only reaching them during runtime should panic or crash. However because of the enabled target features, the rumtime detection macros return true for some features. I think making rustc think that no or only some target features are enabled depending on the backend and not on the target specification would be helpful for both miri and alternative codegen backends. |
If we were to go down this route, how would we decide, e.g., whether some target-feature should return true for cranelift ? If we were to require that cranelift must support all the intrinsics that the feature enables, then I think it's likely that we might never be able to enable any feature for cranelift. If we decide that cranelift only needs to partially support the feature, then some code will panic at run-time when hitting an unsupported intrinsic. |
We could have a query of
I dont really know, but maybe all used intrinsics by most crates using that feature supported would be a good heuristic. |
Should address rust-lang/miri#932